const express = require('express');
const session = require('express-session');
const config = require('../config');
const crypto = require('crypto');
// 添加日志工具（中国标准时间UTC+8）
const logger = (message) => {
    const now = new Date();
    const chinaTime = new Date(now.getTime() + 8 * 60 * 60 * 1000);
    const chinaTimeStr = chinaTime.toISOString().replace('Z', '+08:00');
    console.log(`[${chinaTimeStr}] ${message}`);
};
const bodyParser = require('body-parser');
const path = require('path');
const db = require('./utils/db');
const { sendDingTalk } = require('./utils/dingtalk');
const { generateOTP, verifyOTP, generateTotpUrl } = require('./utils/otp');
const { generatePassword, encrypt, decrypt } = require('./utils/crypto');
const { changePassword } = require('./utils/ssh');
const serverManager = require('./utils/serverManager');

const app = express();
app.use(bodyParser.json());

// 配置会话中间件
app.use(session({
    secret: crypto.randomBytes(32).toString('hex'),
    resave: false,
    saveUninitialized: false,
    cookie: {
        secure: false, // 开发环境使用false，生产环境应改为true并使用HTTPS
        maxAge: 6 * 60 * 60 * 1000 // 会话有效期1天
    }
}));

// 配置静态文件服务
// 使用绝对路径配置静态文件服务
app.use(express.static(path.join(__dirname, '../frontend')));
// 添加对node_modules的静态资源访问
app.use('/node_modules', express.static(path.join(__dirname, '../node_modules')));

// 根路径路由
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, '../frontend/index.html'));
});




// 用户申请接口
app.post('/api/apply', async (req, res) => {
    logger(`接收到新的权限申请: ${JSON.stringify(req.body)}`);
    const { applicant, accountName, targetHost, duration } = req.body;

    // 1. 验证账号是否在可分发列表
    const [rows] = await db.query(
        `SELECT * FROM allowed_accounts WHERE account_name = ? AND target_host = ?`,
        [accountName, targetHost]
    );

    try {
        logger(`debug==============${rows.length},${rows[0].account_name},${rows[0]}`)
    } catch ( error) {
        logger(`[ERROR]:${error.message}`)
    }


    if (!rows.length) {
        logger(`账号 ${accountName} 不在可分发列表中`);
        return res.status(400).json({ error: '该账号不在可分发列表中' });
    }

    // 2. 检查是否已有有效临时密码
    const [activeRequests] = await db.query(
        `SELECT r.* FROM requests r JOIN allowed_accounts a ON r.account_name = a.account_name WHERE r.account_name = ? AND a.target_host = ? AND r.expire_time > NOW()`,
        [accountName, targetHost]
    );

    if (activeRequests.length > 0) {
        activeRequests.forEach((request) => {
            try {
                request.temp_pwd = decrypt(request.temp_pwd);
            } catch (error) {
                logger(`解密临时密码失败: ${error.message}`);
            }
        });
        logger(`账号 ${accountName} 已有有效临时密码，申请ID: ${activeRequests[0].id}, 当前密码: ${activeRequests[0].temp_pwd}`);
    return res.json({
            requestId: activeRequests[0].id,
            action: 'useExisting',
            expireTime: activeRequests[0].expire_time,
            password: activeRequests[0].temp_pwd
        });
    }

    // 验证credentials表中是否有该服务器的root密码
    const [root_credentials] = await db.query(
        `SELECT * FROM credentials WHERE username = 'root' AND c_host = ?`,
        [targetHost]
    );
    if (!root_credentials.length) {
        logger(`服务器 ${targetHost} 未在数据库中配置root密码，无法修改其他用户密码`);
        return res.status(400).json({ error: '当前服务器未配置root密码，无法修改其他用户密码' });
    }

    const [secret__] = await db.query('SELECT totp_secret FROM users WHERE phone = ?', [config.ADMIN_PHONE]);
    if (secret__.length === 0) {
        logger('未找到管理员的TOTP密钥');
        return res.status(500).json({ error: '系统未配置管理员TOTP密钥' });
    }

    // 3. 生成OTP.
    const { secret, token } = generateOTP(secret__[0].totp_secret);
    const otpExpire = new Date(Date.now() + 300000); // 300秒后过期

    // 4. 发送钉钉通知
    logger('发送钉钉通知...');
    await sendDingTalk(
        `[权限申请通知]\n申请人:${applicant}\n申请账号:${accountName}\n目标系统:${targetHost}\n申请时长:${duration}小时\nOTP验证码:${token}`
    );

    // 5. 创建申请记录
    logger('创建申请记录...');
    const [result] = await db.query(
        `INSERT INTO requests (applicant, account_name, duration, otp_code, otp_expire,r_host) VALUES (?, ?, ?, ?, ?, ?)`,
        [applicant, accountName, duration, secret, otpExpire, targetHost]
    );

    logger(`申请成功，生成新OTP，申请ID: ${result.insertId}`);
    res.json({
        requestId: result.insertId,
        action: 'generateNew',
        otpExpire
    });
});

// OTP验证接口
app.post('/api/verify', async (req, res) => {
    logger(`接收到OTP验证请求: ${JSON.stringify(req.body)}`);
    const { requestId, otp } = req.body;

    // 1. 获取申请记录
    const [requests] = await db.query(
        'SELECT * FROM requests WHERE id = ?',
        [requestId]
    );

    if (!requests.length) {
        logger(`申请记录 ${requestId} 不存在`);
    return res.status(404).json({ error: '申请记录不存在' });
    }

    const request = requests[0];

    // // 2. 检查OTP是否有效
    // if (new Date() > new Date(request.otp_expire)) {
    //     logger(`申请记录 ${requestId} 的OTP已过期`);
    // return res.status(400).json({ error: 'OTP已过期' });
    // }
    //=================目前改用TOTP验证，不再过期==================

    const [totp_secret] = await db.query('SELECT totp_secret FROM users WHERE phone = ?', [config.ADMIN_PHONE]);
    if (totp_secret.length === 0) {
        logger('未找到管理员的TOTP密钥');
        return res.status(500).json({ error: '系统未配置管理员TOTP密钥' });
    }
    try {
        logger(`debug=============TOTP_SECRET: ${totp_secret[0].totp_secret}`)
    } catch (error) {
        logger(`[ERROR]:${error.message}`)
    }

    // 3. 使用TOTP验证OTP
    if (!verifyOTP(totp_secret[0].totp_secret, otp)) {
        logger(`申请记录 ${requestId} 的OTP验证失败`);
    return res.status(400).json({ error: 'OTP验证失败' });
    }

    // 4. 生成或获取临时密码
    let password, expireTime;

    if (request.temp_pwd) {
        // 已有有效密码
        password = request.temp_pwd;
        expireTime = request.expire_time;
    } else {
        // 生成新密码
        logger('生成新密码...');
        password = generatePassword();
        const encryptedPwd = encrypt(password);
        expireTime = new Date(Date.now() + request.duration * 3600000);

        // 获取服务器信息
        const [accounts] = await db.query(
            'SELECT target_host FROM allowed_accounts WHERE account_name = ?',
            [request.account_name]
        );
        if (!accounts.length) {
            throw new Error('未找到服务器信息');
        }

        // 更新目标系统密码
        logger(`更新目标系统密码: 账号=${request.account_name}, 主机=${accounts[0].target_host}`);
        try {
            await changePassword(
                request.account_name,
                password,
                request.account_name,
                accounts[0].target_host
            );

            // 只有当密码修改成功时才更新数据库记录
            logger(`更新申请记录 ${requestId} 的临时密码`);
            await db.query(
                `UPDATE requests SET temp_pwd = ?, expire_time = ? WHERE id = ?`,
                [encryptedPwd, expireTime, requestId]
            );
            // 更新密码表的密码
            await db.query(
                `UPDATE credentials SET encrypted_pwd = ? WHERE username = ? and c_host = ?`,
                [encryptedPwd, request.account_name, accounts[0].target_host]
            );
        } catch (err) {
            logger(`[ERROR]:修改密码失败: ${err.message}`);
            if (err.message && err.message.includes('does not exist')) {
                return res.status(500).json({ error: '修改密码失败，该用户不存在' });
            }
            return res.status(500).json({ error: '修改密码失败,请联系管理员' });
        }
    }

    logger(`OTP验证成功，返回临时密码，申请ID: ${requestId}`);
    res.json({ password, expireTime });
});

// 用户注册接口
app.post('/api/register', async (req, res) => {
    logger(`接收到用户注册请求: ${JSON.stringify(req.body)}`);
    const { phone, nickname, password } = req.body;

    try {
        // 验证手机号格式
        if (!/^1[3-9]\d{9}$/.test(phone)) {
            return res.status(400).json({ success: false, message: '请输入有效的手机号' });
        }

        // 验证昵称长度
        if (nickname.length < 2 || nickname.length > 20) {
            return res.status(400).json({ success: false, message: '昵称长度应在2-20个字符之间' });
        }

        // 验证密码长度
        if (password.length < 6 || password.length > 20) {
            return res.status(400).json({ success: false, message: '密码长度应在6-20个字符之间' });
        }

        // 检查手机号是否已注册
        const [existingUsers] = await db.query('SELECT * FROM users WHERE phone = ?', [phone]);
        if (existingUsers.length > 0) {
            return res.status(400).json({ success: false, message: '该手机号已被注册' });
        }

        // 加密密码
        const encryptedPassword = encrypt(password);

        // 插入用户记录
        await db.query(
            'INSERT INTO users (phone, nickname, password, role) VALUES (?, ?, ?, ?)',
            [phone, nickname, encryptedPassword, 'user'] // 默认角色为普通用户
        );

        logger(`用户注册成功: 手机号=${phone}`);
        res.json({ success: true, message: '注册成功' });
    } catch (error) {
        logger(`用户注册失败: ${error.message}`);
        res.status(500).json({ success: false, message: '注册失败，请稍后再试' });
    }
});

// 服务器管理接口 - 添加服务器
app.post('/api/server', async (req, res) => {
    logger(`接收到添加服务器信息请求: ${JSON.stringify(req.body)}`);
    try {
        const serverData = req.body;
        await serverManager.addServerInfo(serverData);
        logger('服务器信息添加成功');
    res.json({ success: true, message: '服务器信息添加成功' });
    } catch (error) {
        logger(`添加服务器信息失败: ${error.message}`);
    logger(`获取服务器信息失败: ${error.message}`);
    res.status(500).json({ success: false, error: error.message });
    }
});

// 服务器管理接口 - 删除服务器
app.delete('/api/server', async (req, res) => {
    logger(`接收到删除服务器信息请求: 主机=${req.query.host}, 用户名=${req.query.username}`);
    try {
        const { host, username } = req.query;
        
        if (!host || !username) {
            return res.status(400).json({ success: false, error: '主机地址和用户名不能为空' });
        }
        
        // 检查用户是否为管理员
        if (!req.session.user || req.session.user.role !== 'admin') {
            logger('非管理员用户尝试删除服务器信息');
            return res.status(403).json({ success: false, error: '权限不足，只有管理员可以删除服务器' });
        }
        
        // 先删除allowed_accounts中的记录
        const [allowedAccounts] = await db.query(
            'SELECT * FROM allowed_accounts WHERE account_name = ? AND target_host = ?',
            [username, host]
        );
        
        if (allowedAccounts.length === 0) {
            return res.status(404).json({ success: false, error: '未找到该服务器的账号信息' });
        }
        
        const credentialId = allowedAccounts[0].credential_id;
        
        await db.query(
            'DELETE FROM allowed_accounts WHERE account_name = ? AND target_host = ?',
            [username, host]
        );
        
        // 再删除credentials中的记录
        await db.query(
            'DELETE FROM credentials WHERE id = ?',
            [credentialId]
        );
        
        logger(`服务器信息删除成功: 主机=${host}, 用户名=${username}`);
        res.json({ success: true, message: '服务器信息删除成功' });
    } catch (error) {
        logger(`删除服务器信息失败: ${error.message}`);
        res.status(500).json({ success: false, error: error.message });
    }
});

// 用户登录接口
app.post('/api/login', async (req, res) => {
    logger(`接收到用户登录请求: ${JSON.stringify(req.body)}`);
    const { phone, password } = req.body;

    try {
        // 验证手机号格式
        if (!/^1[3-9]\d{9}$/.test(phone)) {
            return res.status(400).json({ success: false, message: '请输入有效的手机号' });
        }

        // 查找用户
        const [users] = await db.query('SELECT * FROM users WHERE phone = ?', [phone]);
        if (users.length === 0) {
            return res.status(401).json({ success: false, message: '手机号或密码错误' });
        }

        const user = users[0];
        // 解密密码并验证
        const decryptedPassword = decrypt(user.password);
        if (password !== decryptedPassword) {
            return res.status(401).json({ success: false, message: '手机号或密码错误' });
        }

        // 设置会话
        req.session.user = {
            id: user.id,
            phone: user.phone,
            nickname: user.nickname,
            role: user.role
        };

        logger(`用户登录成功: 手机号=${phone}, 角色=${user.role}`);
        res.json({ success: true, role: user.role });
    } catch (error) {
        logger(`用户登录失败: ${error.message}`);
        res.status(500).json({ success: false, message: '登录失败，请稍后再试' });
    }
});

// 获取所有服务器信息
app.get('/api/servers', async (req, res) => {
    logger('接收到获取所有服务器信息请求');
    try {
        const [rows] = await db.query(
            `SELECT a.*, c.description, c.username, c.encrypted_pwd
             FROM allowed_accounts a
             JOIN credentials c ON a.credential_id = c.id`
        );
        logger(`成功获取 ${rows.length} 条服务器信息`);
        // 解密密码
        rows.forEach(row => {
            try {
                row.encrypted_pwd = decrypt(row.encrypted_pwd);
            } catch (error) {
                logger(`解密服务器密码失败: ${error.message}`);
                row.encrypted_pwd = '未知密码！不符合加密规则';
            }
        });
    res.json(rows);
    } catch (error) {
        res.status(500).json({ success: false, error: error.message });
    }
});

// 获取用户信息接口
app.get('/api/user-info', (req, res) => {
    logger('接收到获取用户信息请求');
    if (req.session.user) {
        logger(`获取用户信息成功: 昵称=${req.session.user.nickname}`);
        res.json({
            nickname: req.session.user.nickname
        });
    } else {
        logger('用户未登录，无法获取用户信息');
        res.status(401).json({ error: '用户未登录' });
    }
});

// 检查登录状态接口
app.get('/api/check-login', (req, res) => {
    logger('接收到检查登录状态请求');
    if (req.session.user) {
        logger(`用户已登录: 手机号=${req.session.user.phone}, 角色=${req.session.user.role}`);
        res.json({
            loggedIn: true,
            role: req.session.user.role
        });
    } else {
        logger('用户未登录');
        res.json({ loggedIn: false });
    }
});

// TOTP设置路由
app.get('/api/totp-setup', async (req, res) => {
    try {
        // 检查用户是否登录
        if (!req.session.user) {
            return res.redirect('/login.html');
        }

        if (config.ADMIN_PHONE == null) {
            return res.status(500).json({ error: '请先在.env文件中配置管理员手机号' });
        }

        const [totp_secret] = await db.query('SELECT totp_secret FROM users WHERE phone = ?',[config.ADMIN_PHONE]);
        if (totp_secret.length === 0) {
            logger('未找到管理员的TOTP密钥');
            return res.status(500).json({ error: '系统未配置管理员TOTP密钥' });
        }
        try {
            logger(`debug=============TOTP_SECRET: ${totp_secret[0].totp_secret}`)
        } catch (error) {
            logger(`[ERROR]:${error.message}`)
        }


        const accountName = req.session.user.phone; // 使用手机号作为账户名
        const {secret} = generateOTP(totp_secret[0].totp_secret); // 生成新的TOTP密钥

        // 这里应该将密钥保存到数据库中，与用户关联
        await db.query('UPDATE users SET totp_secret = ? WHERE phone = ?', [secret, accountName]);

        // 生成TOTP URL
        const totpUrl = generateTotpUrl(secret, accountName);

        // 重定向到前端页面，并带上密钥和账户名参数
        res.redirect(`/totp-setup.html?secret=${encodeURIComponent(secret)}&accountName=${encodeURIComponent(accountName)}`);
    } catch (error) {
        logger(`TOTP设置失败: ${error.message}`);
        res.status(500).json({error: 'TOTP设置失败'});
    }
});

// 退出登录接口
app.post('/api/logout', (req, res) => {
    logger('接收到退出登录请求');
    if (req.session.user) {
        const phone = req.session.user.phone;
        req.session.destroy((err) => {
            if (err) {
                logger(`退出登录失败: ${err.message}`);
                return res.status(500).json({ success: false, message: '退出登录失败' });
            }
            logger(`用户退出登录成功: 手机号=${phone}`);
            res.json({ success: true, message: '退出登录成功' });
        });
    } else {
        logger('用户未登录，无需退出');
        res.json({ success: true, message: '用户未登录' });
    }
});

// 获取版本信息接口
app.get('/api/version', (req, res) => {
    res.json({ version: config.VERSION });
});

// 启动服务
const PORT = 3000;
app.listen(PORT, () => {
    logger(`Server running on port ${PORT}`);
    logger('应用启动成功，定时任务已启动');
    require('./scheduler').start(); // 启动定时任务
});